#include <string.h>
#include <stdlib.h>
#include <table/CHashTable.h>
#include "PBufStr.h"
#include "rtsp_unit.h"
#include "rtsp_resolver.h"
#include "PBStrDispose.h"
#include "CHashTable.h"
#include "rtsp_response.h"

//解析命令
int rtsp_resolver_cmd(RTSPUnit *unit) {
    int ret = RTSPUNIT_RET_WAIT;
    PBufStr *str = &unit->str;
    CHashNode *node;

    ret = PBudStr_read_socket(&unit->str, &unit->socketfile, "\r\n", 2);
    if (ret == RTSPUNIT_RET_SUCCEED) {

        //获取命令
        PBufStr_cut_endchar(str, ' ');
        node = CHashTable_search(&grtsp_cmd_table, str->buf);
        if (node != 0) {

            unit->unit_state = node->data.id;
            if (unit->unit_state == RTSPUNIT_STATE_OPTIONS_RESOLVER) {
                //获取URL
                PBufStr_cut_endchar(str, ' ');
                PBufStr_str_save(&unit->info.url, str->resolver_start);

                //获取版本
                PBufStr_cut_endchar(str, '\r');
                PBufStr_str_save(&unit->info.version, str->resolver_start);
            }
        }
        PBufStr_reset(&unit->str);
        return RTSPUNIT_RET_SUCCEED;
    }
}

//解析参数
int rtsp_resolver_arg(RTSPUnit *unit) {
    int ret;
    PBufStr *str = &unit->str;
    CHashNode *node;
    ret = PBudStr_read_socket(&unit->str, &unit->socketfile, "\r\n", 2);
    if (ret == RTSPUNIT_RET_SUCCEED) {
        //解析结束
        if (str->str_len == 2) {
            PBufStr_reset(&unit->str);
            return RTSPUNIT_RET_SUCCEED;
        }

        PBufStr_cut_endchar(str, ':');
        node = CHashTable_search(&grtsp_arg_table, str->resolver_start);
        if (node != 0) {
            //获取解析函数
            ret = node->data.fun(unit);
        } else {
        }
        PBufStr_reset(&unit->str);
        return RTSPUNIT_RET_WAIT;
    } else {
        return RTSPUNIT_RET_WAIT;
    }
}

int rtsp_resolver_CSeq(RTSPUnit *unit) {
    PBufStr_cut_endchar(&unit->str, '\r');
    unit->info.CSeq = strtol(unit->str.resolver_start, NULL, 10);
    PBufStr_reset(&unit->str);
    return 0;
}

int rtsp_resolver_User_Agent(RTSPUnit *unit) {
    PBufStr_skip_char(&unit->str, ' ');
    PBufStr_cut_endchar(&unit->str, '\r');

    PBufStr_str_save(&unit->info.user_agent, unit->str.resolver_start);
    PBufStr_reset(&unit->str);
    return 0;
}

int rtsp_resolver_Accept(RTSPUnit *unit) {
    PBufStr_skip_char(&unit->str, ' ');
    PBufStr_cut_endchar(&unit->str, '\r');
    if (strcmp(unit->str.resolver_start, "application/sdp") == 0) {
        unit->info.accept_type = RTSPINFO_ACCEPT_TYPE_SDP;
    }
    PBufStr_reset(&unit->str);
    return 0;
}

int rtsp_resolver_Transport(RTSPUnit *unit) {
    PBufStr_skip_char(&unit->str, ' ');
    PBufStr_cut_endchar(&unit->str, ';');
    if (strcmp(unit->str.resolver_start, "RTP/AVP") == 0) {
        unit->info.transport_protocol = RTSPINFO_TRANSPORT_TYPE_UDP;
    } else if (strcmp(unit->str.resolver_start, "RTP/AVP/TCP") == 0) {
        unit->info.transport_protocol = RTSPINFO_TRANSPORT_TYPE_TCP;
    }

    //保存传播方式单播、广播
    PBufStr_cut_endchar(&unit->str, ';');
    if (strcmp(unit->str.resolver_start, "unicast") == 0) {
        unit->info.transport_way = RTSPINFO_TRANSPORT_WAY_UNICAST;
    } else if (strcmp(unit->str.resolver_start, "multicast") == 0) {
        unit->info.transport_way = RTSPINFO_TRANSPORT_WAY_MULTICAST;
    }

    //跳过(UDP时)client_port 或 (TCP时)interleaved
    PBufStr_find_endchar(&unit->str, '=');
    unit->str.buf[unit->str.ridx - 1] = '\0';

    //保存客户端RTP接收端口
    PBufStr_cut_endchar(&unit->str, '-');
    unit->info.crtp_port = strtoul(unit->str.resolver_start, NULL, 10);

    //保存客户端RTCP接收端口
    PBufStr_cut_endchar(&unit->str, '\r');
    unit->info.crtcp_port = strtoul(unit->str.resolver_start, NULL, 10);
    PBufStr_reset(&unit->str);
    return 0;
}

int rtsp_resolver_Session(RTSPUnit *unit) {
    unsigned int session;
    PBufStr_skip_char(&unit->str, ' ');

    //保存客户端数据发送端口
    PBufStr_cut_endchar(&unit->str, '\r');
    session = strtoul(unit->str.resolver_start, NULL, 10);
    PBufStr_reset(&unit->str);
    return 0;
}

int rtsp_resolver_Range(RTSPUnit *unit) {
    unsigned int session;
    PBufStr_skip_char(&unit->str, ' ');

    PBufStr_cut_endchar(&unit->str, '=');

    PBufStr_cut_endchar(&unit->str, '-');

    //保存客户端数据发送端口
    PBufStr_cut_endchar(&unit->str, '\r');
    PBufStr_reset(&unit->str);
    return 0;
}

//参数表
CHashNode grtsp_arg_node_table[] = {
        //  命令                      //解析函数                                           //下一个哈希冲突
        {"CSeq", .data.fun=(int (*)(void *)) rtsp_resolver_CSeq,             NULL},
        {"User-Agent", .data.fun=(int (*)(void *)) rtsp_resolver_User_Agent, NULL},
        {"Accept", .data.fun=(int (*)(void *)) rtsp_resolver_Accept,         NULL},
        {"Transport", .data.fun=(int (*)(void *)) rtsp_resolver_Transport,   NULL},
        {"Session", .data.fun=(int (*)(void *)) rtsp_resolver_Session,       NULL},
        {"Range", .data.fun=(int (*)(void *)) rtsp_resolver_Range,           NULL},
};


//命令表
CHashNode grtsp_cmd_node_table[] = {
        //  命令                      //命令号                           //下一个哈希冲突
        {"OPTIONS", .data.id=RTSPUNIT_STATE_OPTIONS_RESOLVER,   NULL},
        {"DESCRIBE", .data.id=RTSPUNIT_STATE_DESCRIBE_RESOLVER, NULL},
        {"SETUP", .data.id=RTSPUNIT_STATE_SETUP_RESOLVER,       NULL},
        {"PLAY", .data.id=RTSPUNIT_STATE_PLAY_RESOLVER,         NULL},
        {"PAUSE", .data.id=RTSPUNIT_STATE_PAUSE_RESOLVER,       NULL},
        {"TEARDOWN", .data.id=RTSPUNIT_STATE_TEARDOWN_RESOLVER, NULL},
};

//
////单词表
//CHashNode grtsp_word_node_table[] = {
//        //  单词                //单词号    //下一个哈希冲突
//        {"CSeq", .data.id=0,       NULL},
//        {"User-Agent", .data.id=1, NULL},
//};


CHashNode *grtsp_cmd_list[16];
CHashNode *rtsp_arg_list[32];
CHashNode *grtsp_word_list[128];

CHashTable grtsp_cmd_table;
CHashTable grtsp_arg_table;
CHashTable grtsp_word_table;

void gword_hash_table_init() {
    CHashTable_init(&grtsp_cmd_table, grtsp_cmd_list, 16);
    CHashTable_init(&grtsp_arg_table, rtsp_arg_list, 32);
    CHashTable_init(&grtsp_word_table, grtsp_word_list, 128);

    for (int i = 0; i < (sizeof(grtsp_cmd_node_table) / sizeof(CHashNode)); i++) {
        CHashTable_insert(&grtsp_cmd_table, &grtsp_cmd_node_table[i]);
    }

    for (int i = 0; i < (sizeof(grtsp_arg_node_table) / sizeof(CHashNode)); i++) {
        CHashTable_insert(&grtsp_arg_table, &grtsp_arg_node_table[i]);
    }

//    for (int i = 0; i < (sizeof(grtsp_word_node_table) / sizeof(CHashNode)); i++) {
//        CHashTable_insert(&grtsp_word_table, &grtsp_word_node_table[i]);
//    }
}